package com.ywh.composetest.activity

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.res.Resources
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.SecureFlagPolicy
import com.ywh.composetest.DataClass
import com.ywh.composetest.DataClass2
import com.ywh.composetest.ExternalClass
import com.ywh.composetest.MyClass
import com.ywh.composetest.MyClass3
import com.ywh.composetest.SealedClass
import com.ywh.composetest.ui.theme.ComposeTestTheme
import com.ywh.composetest.widget.BoxTextCompose
import com.ywh.composetest.widget.CommonBottomSheet
import com.ywh.composetest.widget.LoadAndroidView
import com.ywh.composetest.widget.SpacerVertical
import com.ywh.composetest.widget.TextAnnotatedStringCompose
import com.ywh.composetest.widget.TextFieldLengthFilter
import com.ywh.composetest.widget.TextFieldNumberFilter
import com.ywh.composetest.widget.TextFieldTestCompose
import com.ywh.composetest.widget.TextTestCompose

/**
 * 1、基础组件，Material Design组件
 * 2、compose环境+compose项目结构
 * 3、嵌套，滚动，输入交互,组件组合重用的控件
 * 4、嵌套原生View，与原生View交互
 * 5、状态管理
 * 6、remember 、MutableState 、 DerivedState
 * 7、帧处理机制、布局优化、性能优化  、Jetsnack分析
 *
 * Text  文本
 * TextField  输入框
 *
 * Image     resourcePainter
 * AsyncImage    coil
 *
 * HorizontalPager
 * VerticalPager
 *
 * LazyHorizontalGrid
 * LazyVerticalGrid
 * LazyColumn
 * LazyRow
 *
 * Popup
 * Dialog
 *
 * CircularProgressIndicator
 * LinearProgressIndicator
 *
 * Box
 * Spacer
 * Row
 * Column
 *
 * FlowRow
 * FlowColumn
 *
 * AndroidView: composable函数加载原生的xml布局或View
 *      AndroidView(factory = {
 *         LayoutInflater.from(it).inflate(layoutId, null, false)
 *     }, modifier = Modifier.size(100.dp)) {
 *         it.setProgress(progress = progress)
 *     }
 * ComposeView:在xml中定义一个composeView，setContent{ @Composable函数 }
 *
 * UI常见属性
 * 1、Modifier:
 *  当链式调用 Modifier 的时候，先调用的会包裹后调用的，最里层是 Layout Node。
 *  调用 .size() 生成 SizeElement。
 *  调用 .background() 生成 CombinedModifier(outer  = SizeElement, inner = BackgroundElement)。
 *  调用 .padding() 生成 CombinedModifier(outer = CombinedModifier(SizeElement, BackgroundElement)， inner = PaddingElement)。
 *
 *
 * 1.CompositionLocalProvider + staticCompositionLocalOf、CompositionLocalOf
 *      CompositionLocalProvider提供作用域，修改的值只在作用域内有效
 *      CompositionLocalOf:值改变时，只有compositionLocalProvider作用域下使用current值的组件重组
 *      staticCompositionLocalOf:值改变时，compositionLocalProvider作用域下全重组，所以staticCompositionLocalOf适用于常量，不改变的值
 * 2.remember   derivedStateOf   rememberSaveable
 * 3.MutableState
 * 4.LaunchedEffect
 * 5.DisposableEffect：允许开发者在组件进入和离开某个生命周期阶段时执行特定的操作，如注册和注销观察者。
 * 6.SideEffect
 *
 * material3:
 * Card
 * Icon
 * IconButton
 * TextField
 * Button
 * Switch
 * ModalBottomSheet
 */

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val statusBarHeight: Int = Resources.getSystem().getDimensionPixelSize(
            Resources.getSystem().getIdentifier("status_bar_height", "dimen", "android")
        )

        setContent {
            ComposeTestTheme {
                // A surface container using the 'background' color from the theme
                Scaffold(
                    modifier = Modifier.fillMaxSize()
                ) { p ->
                    ContentList(statusBarHeight, this)
                }
            }
        }
    }
}

/**
 * 优化：
 * 组件A中有一个组件B,B点击会触发state改变的，需要把组件B提出来一个Composable函数，state参数传进去
 * 这样点击B时不会触发A重组
 * 如果在A中直接写B和点击的代码，B点击后A组件也会重组
 */
@Composable
private fun ContentList(statusBarHeight: Int, activity: Activity?) {
    Log.e("MainActivity", "ContentList")
    val scrollState = rememberScrollState()
    val testLaunchedEffect = remember {
        mutableStateOf(false)
    }
    val inputContentState = remember {
        mutableStateOf("")
    }
    val showPopupState = remember {
        mutableStateOf(false)
    }

    val showDialogCenterState = remember {
        mutableStateOf(false)
    }

    val showBottomSheetState = remember {
        mutableStateOf(false)
    }

    val popupOffset = remember {
        mutableStateOf(Offset(0f, 0f))
    }

    PopupTestCompose(showPopupState, popupOffset, statusBarHeight)
    DialogCenterTestCompose(showDialogCenterState)
    BottomSheetTestCompose(showBottomSheetState)


    BoxWithConstraints(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(scrollState)
    ) {
        Column(modifier = Modifier.padding(12.dp)) {
            TextTestCompose()
            Spacer(modifier = Modifier.height(10.dp))
            TextAnnotatedStringCompose()


            TextFieldTestCompose(
                inputContentState,
                arrayListOf(TextFieldLengthFilter(10), TextFieldNumberFilter())
            ) {
                Log.e("TextFieldTest", ":onValueChanged:${it}")
            }
            Spacer(modifier = Modifier.height(10.dp))

            Image(
                painter = painterResource(id = androidx.core.R.drawable.ic_call_answer),
                contentDescription = "",
                alignment = Alignment.Center,
                contentScale = ContentScale.Crop,
                alpha = 0.5f,
                colorFilter = ColorFilter.tint(Color.Red)
            )

            Spacer(modifier = Modifier.height(10.dp))

            CircularProgressIndicator(
                modifier = Modifier.size(30.dp),
                color = Color.Red,
                strokeWidth = 3.dp,
                strokeCap = StrokeCap.Round,
                trackColor = Color.Green
            )
            LinearProgressIndicator(
                color = Color.Red,
                strokeCap = StrokeCap.Round,
                trackColor = Color.Green
            )

            Button(onClick = {
                activity?.startActivity(Intent(activity, PagerActivity::class.java))
            }) {
                Text(text = "Pager")
            }


            LoadAndroidView(width = 200.dp, height = 40.dp)
            SpacerVertical(height = 10.dp)
            BoxTextCompose(content = "ComposeView") {
                activity?.startActivity(Intent(activity, ComposeViewTestActivity::class.java))
            }
            SpacerVertical(height = 10.dp)

            PopupBtnCompose(popupOffset) {
                showPopupState.value = true
            }

            Spacer(modifier = Modifier.height(3.dp))

            BoxTextCompose(content = "Dialog") {
                showDialogCenterState.value = true
            }

            Spacer(modifier = Modifier.height(3.dp))

            BoxTextCompose(content = "BottomSheet") {
                showBottomSheetState.value = true
            }

            SpacerVertical(height = 10.dp)
            BoxTextCompose(content = "CompositionLocalProvider") {
                activity?.startActivity(Intent(activity, CompositionLocalProviderTestActivity::class.java))
            }
            SpacerVertical(height = 10.dp)
            BoxTextCompose(content = "DisposableEffect") {
                activity?.startActivity(Intent(activity, DisposableEffectActivity::class.java))
            }
            SpacerVertical(height = 10.dp)
            TestLaunchEffectCompose(testLaunchedEffect)

            Spacer(modifier = Modifier.height(10.dp))

            Button(onClick = {
                activity?.startActivity(Intent(activity, ParcelizeActivity::class.java).apply {
                    putExtra("dataClass", DataClass("ywh", 18).apply {
                        address = "武汉市"
                    })

                    putExtra("dataClass2", DataClass2("ywh", 18).apply {
                        address = "武汉市"
                    })

                    putExtra("myClass", MyClass("ywh", 18).apply {
                        address = "武汉市"
                    })

                    putExtra("sealedClassA", SealedClass.A("ywh"))
                    putExtra("sealedClassB", SealedClass.B(19))
                    putExtra("sealedClassC", SealedClass.C)


                    val externalClass = ExternalClass("ywh123", 20)
                    Log.e(
                        "KotlinParcelize",
                        "MainActivity: externalClass:${externalClass.hashCode()}"
                    )
                    putExtra("external", MyClass3(externalClass))
                })

            }) {
                Text(text = "Parcelize测试")
            }

            SpacerVertical(height = 10.dp)
            BoxTextCompose(content = "手势") {
                activity?.startActivity(Intent(activity, GestureActivity::class.java))
            }

            SpacerVertical(height = 10.dp)
            BoxTextCompose(content = "动画") {
                activity?.startActivity(Intent(activity, AnimatableActivity::class.java))
            }

            SpacerVertical(height = 10.dp)
            BoxTextCompose(content = "List") {
                activity?.startActivity(Intent(activity, LazyColumnActivity::class.java))
            }

            SpacerVertical(height = 10.dp)

            BoxTextCompose(content = "Compose-${RefreshTestActivity.TYPE_ONE_PRO_ONE_STATE}") {
                activity?.startActivity(Intent(activity, RefreshTestActivity::class.java))
            }

            SpacerVertical(height = 10.dp)
            TestFlowRowCompose()


            SpacerVertical(height = 100.dp)
        }
    }
}

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun TestFlowRowCompose() {
    Column {
        Text(text = "FlowRow")
        FlowRow(
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalArrangement = Arrangement.spacedBy(6.dp), maxItemsInEachRow = 5
        ) {
            BoxTextCompose(content = "a") {
            }
            BoxTextCompose(content = "xxxxxxxoijk") {
            }
            BoxTextCompose(content = "jksajfkjs") {
            }
            BoxTextCompose(content = "四个字呀") {
            }
            BoxTextCompose(content = "设计费卡口") {
            }
            BoxTextCompose(content = "设计费卡口") {
            }
            BoxTextCompose(content = "设计费") {
            }
        }
    }
}

@Composable
fun BottomSheetTestCompose(showBottomSheetState: MutableState<Boolean>) {
    if (showBottomSheetState.value) {
        CommonBottomSheet(showBottomSheetState, RoundedCornerShape(8.dp), Color.Red) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(200.dp)
            ) {
                Text(text = "哈哈哈")
            }
        }
    }
}

@Composable
fun DialogCenterTestCompose(showDialogCenterState: MutableState<Boolean>) {
    if (showDialogCenterState.value) {
        Dialog(
            onDismissRequest = { showDialogCenterState.value = false },
            properties = DialogProperties(
                dismissOnBackPress = true,
                dismissOnClickOutside = true,
                securePolicy = SecureFlagPolicy.SecureOn,// WindowManager.LayoutParams.FLAG_SECURE 安全属性，比如不允许截图
                usePlatformDefaultWidth = false,//默认为true,无法占满屏幕宽，false：就是组件自己的宽度
                decorFitsSystemWindows = true
            )
        ) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight()
                    .background(Color.White, shape = RoundedCornerShape(10.dp)),
                contentAlignment = Alignment.Center
            ) {
                Text(text = "这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog这是一个dialog")
            }
        }
    }
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PopupBtnCompose(popupOffset: MutableState<Offset>, onClick: () -> Unit) {
    Box(
        modifier = Modifier
            .size(80.dp, 44.dp)
            .background(Color.Green, shape = RoundedCornerShape(22.dp))
            .onGloballyPositioned {
                popupOffset.value = it.positionInWindow()
                val size = it.size
                val position = it.positionInWindow()
                Log.e(
                    "ModifierTest",
                    "onGloballyPositioned:size:${size.toString()},position:${position.toString()}"
                )
            }
            .onSizeChanged {
                Log.e("ModifierTest", "onSizeChanged:size:${it.toString()}")
            }
            .combinedClickable(onLongClick = {

            }) {
                onClick.invoke()
            },
        contentAlignment = Alignment.Center
    ) {
        Text(text = "Popup")
    }
}

@Composable
fun PopupTestCompose(
    showPopupState: MutableState<Boolean>,
    popupOffset: MutableState<Offset>,
    statusBarHeight: Int
) {
    if (showPopupState.value) {
        Popup(
            offset = IntOffset(
                popupOffset.value.x.toInt(),
                popupOffset.value.y.toInt() - statusBarHeight
            ),
            onDismissRequest = {
                showPopupState.value = false
            }) {
            Box(modifier = Modifier
                .size(40.dp)
                .background(Color.Red)
                .clickable {
                    showPopupState.value = false
                }) {
                Text(text = "Popup")
            }
        }
    }
}

@Composable
fun TestLaunchEffectCompose(testLaunchedEffect: MutableState<Boolean>) {
    Log.e("MainActivity", "TestLaunchEffectCompose")

    Item("设置testLaunchedEffect=true") {
        testLaunchedEffect.value = true
    }
    Item("设置testLaunchedEffect=false") {
        testLaunchedEffect.value = false
    }
    Item("设置testLaunchedEffect相反值") {
        testLaunchedEffect.value = !testLaunchedEffect.value
    }

    //当前composable函数绘制时执行一次
    LaunchedEffect(Unit) {
        Log.e("LaunchEffect", "work")
    }

    //当前composable函数绘制时执行一次，值改变是执行一次
    LaunchedEffect(testLaunchedEffect.value) {
        Log.e("LaunchEffect", "testLaunchedEffect")
    }

    //testLaunchedEffect的值改变并且为true时执行一次
    if (testLaunchedEffect.value) {
        Log.e("LaunchEffect", "22:testLaunchedEffect")
    }
}

@Composable
private fun Item(text: String, onClick: () -> Unit) {
    Column(
        verticalArrangement = Arrangement.Center
    ) {
        Box(modifier = Modifier
            .fillMaxWidth()
            .height(40.dp)
            .clickable {
                onClick.invoke()
            }
            .border(width = 1.dp, color = Color.Red, RoundedCornerShape(8.dp))
        ) {
            Text(
                text = text, textAlign = TextAlign.Center
            )
        }
        Spacer(modifier = Modifier.height(8.dp))
    }
}

@Preview(showBackground = true, backgroundColor = 0xffffffff)
@Composable
fun GreetingPreview() {
    ComposeTestTheme {
        ContentList(0, null)
    }
}